package application.mvc.sys.index;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Timer;
import java.util.TimerTask;

import com.jfinal.ext.kit.DateKit;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;

import application.common.model.Board;
import application.common.model.CameraRecord;
import application.common.model.Config;
import application.common.model.FaultBox;
import application.common.model.StoreBox;
import application.common.model.User;
import application.common.render.HttpClientResult;
import application.common.render.WarningProperty;
import application.common.ui.AuthorizeDialog;
import application.common.ui.AuthorizeUserDialog;
import application.common.ui.ProgressStage;
import application.common.ui.ScreenDialog;
import application.common.util.FiltUtil;
import application.common.util.HandleMessgeUtil;
import application.common.util.HttpUtil;
import application.common.util.PwdUtil;
import application.common.util.RouteUtil;
import application.common.util.ShiroUtil;
import application.common.util.UuidUtil;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class IndexController implements Initializable {
	protected final Log log = Log.getLog(getClass());

	@FXML
	private Label headerLabel;
	@FXML
	private Label serverPhoneLabel;

	@FXML
	private Label copyrightLabel;

	@FXML
	private Button loginBtn;

	@FXML
	private Pane saveBarPane;

	@FXML
	private Pane assetPiePane;

	@FXML
	private Label boxTotalLabel;

	@FXML
	private Rectangle usedRectangle;

	@FXML
	private Label usedTotal;

	@FXML
	private Rectangle freeRectangle;

	@FXML
	private Label freeTotal;

	@FXML
	private Rectangle faultRectangle;

	@FXML
	private Label faultTotal;

	@FXML
	private Canvas handleCanvas;

	@FXML
	private Label handleTotalLabel;

	@FXML
	private Label detainTotal;

	@FXML
	private Label arrestTotal;

	@FXML
	private Label bailPendingTrialTotal;

	@FXML
	private Label supervisionResidenceTotal;

	@FXML
	private Label prosecutionTotal;

	@FXML
	private Label criminalJudgmentTotal;

	@FXML
	private TableView<WarningProperty> warningTableView;

	private final ObservableList<WarningProperty> warningPropertys = FXCollections.observableArrayList();

	@FXML
	private ImageView adImageView;

	private boolean isDestroy = false;

	public void initialize(URL location, ResourceBundle resources) {
		headerLabel.setText(ShiroUtil.getSoftName());
		serverPhoneLabel.setText(ShiroUtil.getPhone());
		cabUsed();
		archivesStatistics();
		warning();
		version();
		screenPross();
		HandleMessgeUtil.setIndexController(this);
	}

	public void message(String message) {

	}

	/**
	 * 卷宗柜使用情况
	 */
	private void cabUsed() {
		int total = Db.queryInt("select sum(boxTotal) from " + Board.TABLE_NAME);
		int used = Db.queryInt("select count(id) from " + StoreBox.TABLE_NAME);
		int fault = Db.queryInt("select count(id) from " + FaultBox.TABLE_NAME);
		int free = total - used - fault;
		boxTotalLabel.setText(total + "(个)");
		usedRectangle.setWidth((274.2 / total) * used);
		usedTotal.setText(used + "");
		freeRectangle.setWidth((274.2 / total) * free);
		freeTotal.setText(free + "");
		faultRectangle.setWidth((274.2 / total) * fault);
		faultTotal.setText(fault + "");
	}

	/**
	 * 年内案件办理情况
	 */
	private Timer archivesStatisticsTimer;

	private void archivesStatistics() {
		repaint(null);
		archivesStatisticsTimer = new Timer();
		archivesStatisticsTimer.schedule(new TimerTask() {
			@Override
			public void run() {
				if (ShiroUtil.getConfig() != null && !StrKit.isBlank(ShiroUtil.getConfig().getSynURL())) {
					try {
						HttpClientResult httpClientResult = HttpUtil
								.doGet(String.format("%s/api/archive/handleStatistics?cabinetId=%s",
										ShiroUtil.getConfig().getSynURL(), ShiroUtil.getAuth()));
						if (httpClientResult == null) {
							isEnd = true;
							return;
						}
						if (httpClientResult.getCode() != 200) {
							isEnd = true;
							return;
						}
						String content = httpClientResult.getContent();
						if (StrKit.isBlank(content)) {
							isEnd = true;
							return;
						}
						JSONObject jsonObject = JSONObject.fromObject(content);
						if (jsonObject == null) {
							isEnd = true;
							return;
						}
						if (jsonObject.has("code")) {
							int code = jsonObject.getInt("code");
							if (code != 200) {
								isEnd = true;
								return;
							}
							if (jsonObject.has("data")) {
								String data = jsonObject.getString("data");
								if (StrKit.isBlank(data)) {
									isEnd = true;
									return;
								}
								JSONObject dataObject = JSONObject.fromObject(data);
								if (dataObject == null) {
									isEnd = true;
									return;
								}
								repaint(dataObject);
								isEnd = true;
							} else {
								isEnd = true;
							}
						} else {
							isEnd = true;
						}
					} catch (Exception e) {
						isEnd = true;
					}
				}
			}
		}, 5000, 1000 * 60 * 60);
	}

	public static double chufa(double a, double b) {
		if (b == 0) {
			return 0;
		}
		DecimalFormat df = new DecimalFormat("0.00");
		return Double.parseDouble(df.format((float) a / b));
	}

	private void repaint(JSONObject data) {
		Platform.runLater(new Runnable() {
			public void run() {
				try {
					int total = 0;
					int detain = 0;
					int arrest = 0;
					int pending = 0;
					int monitor = 0;
					int prosecution = 0;
					int sentence = 0;

					if (data != null && data.containsKey("total")) {
						total = data.getInt("total");
					}
					if (data != null && data.containsKey("detain")) {
						detain = data.getInt("detain");
					}
					if (data != null && data.containsKey("arrest")) {
						arrest = data.getInt("arrest");
					}
					if (data != null && data.containsKey("pending")) {
						pending = data.getInt("pending");
					}
					if (data != null && data.containsKey("monitor")) {
						monitor = data.getInt("monitor");
					}
					if (data != null && data.containsKey("prosecution")) {
						prosecution = data.getInt("prosecution");
					}
					if (data != null && data.containsKey("sentence")) {
						sentence = data.getInt("sentence");
					}

					handleCanvas.getGraphicsContext2D().restore();
					handleTotalLabel.setText(total + "(件)");

					GraphicsContext gc = handleCanvas.getGraphicsContext2D();
					gc.setLineWidth(6);
					LinearGradient linearGradient_out_line = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
							new Stop[] { new Stop(0, Color.rgb(51, 75, 97, 1)),
									new Stop(1, Color.rgb(109, 138, 165, 1)), });
					gc.setStroke(linearGradient_out_line);
					gc.strokeOval(60, 15, 60, 60);
					gc.strokeOval(180, 15, 60, 60);
					gc.strokeOval(300, 15, 60, 60);

					gc.strokeOval(60, 105, 60, 60);
					gc.strokeOval(180, 105, 60, 60);
					gc.strokeOval(300, 105, 60, 60);

					LinearGradient linearGradient_in_line = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
							new Stop[] { new Stop(0, Color.rgb(154, 231, 254, 1)),
									new Stop(1, Color.rgb(53, 174, 211, 1)), new Stop(2, Color.rgb(18, 157, 205, 1)) });
					gc.setStroke(linearGradient_in_line);

					double arc1 = chufa(360, total) * detain;
					double arc2 = chufa(360, total) * arrest;
					double arc3 = chufa(360, total) * pending;
					double arc4 = chufa(360, total) * monitor;
					double arc5 = chufa(360, total) * prosecution;
					double arc6 = chufa(360, total) * sentence;

					gc.strokeArc(60, 15, 60, 60, 90, arc1, ArcType.OPEN);
					gc.strokeArc(180, 15, 60, 60, 90, arc2, ArcType.OPEN);
					gc.strokeArc(300, 15, 60, 60, 90, arc3, ArcType.OPEN);

					gc.strokeArc(60, 105, 60, 60, 90, arc4, ArcType.OPEN);
					gc.strokeArc(180, 105, 60, 60, 90, arc5, ArcType.OPEN);
					gc.strokeArc(300, 105, 60, 60, 90, arc6, ArcType.OPEN);

					detainTotal.setText("" + detain);
					arrestTotal.setText("" + arrest);
					bailPendingTrialTotal.setText("" + pending);
					supervisionResidenceTotal.setText("" + monitor);
					prosecutionTotal.setText("" + prosecution);
					criminalJudgmentTotal.setText("" + sentence);

				} catch (Exception e) {
				}
			}
		});
	}

	/**
	 * 预警
	 */
	private Timer versionTimer;
	boolean isVersionEnd = false;

	private void version() {
		versionTimer = new Timer();
		versionTimer.schedule(new TimerTask() {
			@Override
			public void run() {
				if (ShiroUtil.getConfig() != null && !StrKit.isBlank(ShiroUtil.getConfig().getSynURL())
						&& !StrKit.isBlank(ShiroUtil.getConfig().getSoftMainName())
						&& !StrKit.isBlank(ShiroUtil.getConfig().getSoftPath())
						&& !StrKit.isBlank(ShiroUtil.getConfig().getSoftBackPath())
						&& !StrKit.isBlank(ShiroUtil.getConfig().getUpdateSoft())) {
					try {
						HttpClientResult httpClientResult = HttpUtil
								.doGet(String.format("%s/api/soft/getVersion?cabinetId=%s",
										ShiroUtil.getConfig().getSynURL(), ShiroUtil.getAuth()));
						if (httpClientResult == null) {
							isVersionEnd = true;
							return;
						}
						if (httpClientResult.getCode() != 200) {
							isVersionEnd = true;
							return;
						}
						String content = httpClientResult.getContent();
						if (StrKit.isBlank(content)) {
							isVersionEnd = true;
							return;
						}
						System.out.println("content=" + content);
						JSONObject jsonObject = JSONObject.fromObject(content);
						if (jsonObject == null) {
							isVersionEnd = true;
							return;
						}
						if (jsonObject.has("code")) {
							int code = jsonObject.getInt("code");
							if (code != 200) {
								isVersionEnd = true;
								return;
							}
							if (jsonObject.has("data")) {
								String data = jsonObject.getString("data");
								if (StrKit.isBlank(data)) {
									isVersionEnd = true;
									return;
								}
								JSONObject dataObject = JSONObject.fromObject(data);
								if (dataObject == null) {
									isVersionEnd = true;
									return;
								}
								Config config = Config.dao.findById(ShiroUtil.getConfig().getId());
								double number = dataObject.getDouble("number");
								String version = config.getVersion();
								if (Double.parseDouble(version) < number) {
									if (!isDestroy) {
										Runtime re = Runtime.getRuntime();
										BufferedReader output;
										try {
											File file = new File(ShiroUtil.getConfig().getUpdateSoft());
											if (file.exists()) {
												Process cmd = re
														.exec("java -jar " + ShiroUtil.getConfig().getUpdateSoft());
												output = new BufferedReader(
														new InputStreamReader(cmd.getInputStream()));
												String resultOutput = output.readLine();
												isDestroy = true;
												log.debug("升级中！" + resultOutput);
												if (ShiroUtil.getMainProcess() != null) {
													ShiroUtil.getMainProcess().stop();
												}
												System.exit(0);
											} else {
												log.debug("无法升级，未配置升级程序！");
											}
											isVersionEnd = true;
											return;
										} catch (IOException ioe) {
											ioe.printStackTrace();
											isVersionEnd = true;
											return;
										}
									}
								} else {
									isVersionEnd = false;
								}
								return;
							} else {
								isVersionEnd = true;
							}
						} else {
							isVersionEnd = true;
						}
					} catch (Exception e) {
						isVersionEnd = true;
					}
				}
			}
		}, 1000, 1000 * 60 * 10);
	}

	/**
	 * 预警
	 */
	private Timer archivesWarningTimer;
	boolean isEnd = false;

	@SuppressWarnings("unchecked")
	private void warning() {

		TableColumn<WarningProperty, String> director = new TableColumn<WarningProperty, String>("办案人");
		director.setMinWidth(150);
		director.setCellValueFactory(new PropertyValueFactory<WarningProperty, String>("director"));
		director.setResizable(false);
		director.setSortable(false);
		director.setEditable(false);

		TableColumn<WarningProperty, String> suspectName = new TableColumn<WarningProperty, String>("嫌疑人");
		suspectName.setMinWidth(150);
		suspectName.setCellValueFactory(new PropertyValueFactory<WarningProperty, String>("suspectName"));
		suspectName.setResizable(false);
		suspectName.setSortable(false);
		suspectName.setEditable(false);

		TableColumn<WarningProperty, String> archiveNo = new TableColumn<WarningProperty, String>("案件号");
		archiveNo.setMinWidth(150);
		archiveNo.setCellValueFactory(new PropertyValueFactory<WarningProperty, String>("archiveNo"));
		archiveNo.setResizable(false);
		archiveNo.setSortable(false);
		archiveNo.setEditable(false);

		TableColumn<WarningProperty, String> expireDate = new TableColumn<WarningProperty, String>("到期日期");
		expireDate.setMinWidth(150);
		expireDate.setCellValueFactory(new PropertyValueFactory<WarningProperty, String>("expireDate"));
		expireDate.setResizable(false);
		expireDate.setSortable(false);
		expireDate.setEditable(false);

		TableColumn<WarningProperty, String> cause = new TableColumn<WarningProperty, String>("案由");
		cause.setMinWidth(300);
		cause.setCellValueFactory(new PropertyValueFactory<WarningProperty, String>("cause"));
		cause.setResizable(false);
		cause.setSortable(false);
		cause.setEditable(false);

		warningTableView.getColumns().addAll(archiveNo, cause, suspectName, expireDate,director);
		warningTableView.setItems(warningPropertys);
		archivesWarningTimer = new Timer();
		archivesWarningTimer.schedule(new TimerTask() {
			@Override
			public void run() {
				if (ShiroUtil.getConfig() != null && !StrKit.isBlank(ShiroUtil.getConfig().getSynURL())) {
					try {
						HttpClientResult httpClientResult = HttpUtil
								.doGet(String.format("%s/api/archive/warnings?cabinetId=%s",
										ShiroUtil.getConfig().getSynURL(), ShiroUtil.getAuth()));
						if (httpClientResult == null) {
							isEnd = true;
							return;
						}
						if (httpClientResult.getCode() != 200) {
							isEnd = true;
							return;
						}
						String content = httpClientResult.getContent();
						if (StrKit.isBlank(content)) {
							isEnd = true;
							return;
						}
						JSONObject jsonObject = JSONObject.fromObject(content);
						if (jsonObject == null) {
							isEnd = true;
							return;
						}
						if (jsonObject.has("code")) {
							int code = jsonObject.getInt("code");
							if (code != 200) {
								isEnd = true;
								return;
							}
							if (jsonObject.has("data")) {
								String data = jsonObject.getString("data");
								if (StrKit.isBlank(data)) {
									isEnd = true;
									return;
								}
								JSONArray array = JSONArray.fromObject(data);
								if (array == null || array.size() == 0) {
									isEnd = true;
									return;
								}
								warningPropertys.clear();
								for (Object object : array) {
									JSONObject row = JSONObject.fromObject(object);
									if (row != null) {
										warningPropertys.add(new WarningProperty(row));
									}
								}
								isEnd = true;
							} else {
								isEnd = true;
							}
						} else {
							isEnd = true;
						}
					} catch (Exception e) {
						isEnd = true;
					}
				}
			}
		}, 1000, 1000 * 60 * 5);
	}

	private Timeline animation;
	private int screen = 60;
	private ScreenDialog screenDialog;
	
	/**
	 * 屏幕保倒计时
	 */
	public void screenPross() {
		if (StrKit.isBlank(ShiroUtil.getConfig().getPicturePath())) {
			return;
		}
		screenDialog=null;
		screen = 60;
		animation = new Timeline(new KeyFrame(Duration.millis(1000), new EventHandler<ActionEvent>() {
			public void handle(ActionEvent event) {
				if (screen == 0) {
					List<File> files=FiltUtil.getList(ShiroUtil.getConfig().getPicturePath());
					if (files!=null  && files.size() > 0) {
						if (animation != null) {
							animation.stop();
						}
						Platform.runLater(new Runnable() {
							public void run() {
								if (!isDestroy) {
									screenDialog = new ScreenDialog(RouteUtil.mainStage);
								}
							}
						});
					} else {
						screen = 60;
					}
				} else {
					screen--;
				}
			}
		}));
		animation.setCycleCount(Timeline.INDEFINITE);
		animation.play();
	}

	public void destroy() {
		HandleMessgeUtil.setIndexController(null);
		try {
			ShiroUtil.getConfig().setState("0");
			ShiroUtil.getConfig().update();
			CameraRecord cameraRecord = new CameraRecord();
			cameraRecord.setId(UuidUtil.getUUID());
			cameraRecord.setStartTime(DateKit.toStr(new Date(System.currentTimeMillis()), "yyyy-MM-dd hh:mm:ss"));
			if (cameraRecord.save()) {
				ShiroUtil.setCameraRecord(cameraRecord);
			}
		} catch (Exception e) {
		}
//		if(adTimer!=null) {
//			adTimer.cancel();
//			adTimer=null;
//		}
		if (archivesWarningTimer != null) {
			archivesWarningTimer.cancel();
			archivesWarningTimer = null;
		}

		if (archivesStatisticsTimer != null) {
			archivesStatisticsTimer.cancel();
			archivesStatisticsTimer = null;
		}

		if (versionTimer != null) {
			versionTimer.cancel();
			versionTimer = null;
		}

		if (animation != null) {
			animation.stop();
			animation = null;
		}
		
		if(screenDialog!=null) {
			screenDialog.close();
			screenDialog = null;
		}
	}

	public void login(ActionEvent event) {
		if (!isDestroy) {
			isDestroy = true;
			ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
				@Override
				protected Void call() throws Exception {
					destroy();
					RouteUtil.goLogin();
					return null;
				}
			}, "前往登录页面中...").show();
		}
	}

	public void loginPwd() {
		if (!isDestroy) {
			isDestroy = true;
			final AuthorizeDialog authorizeDialog = new AuthorizeDialog(RouteUtil.mainStage);
			authorizeDialog.addListner(new EventHandler<ActionEvent>() {
				public void handle(ActionEvent event) {
					String pwd = authorizeDialog.getPassword();
					if (StrKit.isBlank(pwd)) {
						authorizeDialog.setMsg("密码不可以空！");
						isDestroy = false;
						return;
					}
					if (ShiroUtil.getConfig() != null && !StrKit.isBlank(ShiroUtil.getConfig().getPassword())) {
						if (StrKit.equals(PwdUtil.encrypt(pwd), ShiroUtil.getConfig().getPassword())) {
							authorizeDialog.close();

							ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
								@Override
								protected Void call() throws Exception {
									destroy();
									RouteUtil.goConfig();
									return null;
								}
							}, "前往设置页面中...").show();

						} else {
							authorizeDialog.setMsg("密码错误！");
						}
					} else {

						if (StrKit.equals("123456", pwd)) {
							authorizeDialog.close();
							ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
								@Override
								protected Void call() throws Exception {
									destroy();
									RouteUtil.goConfig();
									return null;
								}
							}, "前往设置页面中...").show();
						} else {
							authorizeDialog.setMsg("密码错误！");
						}
					}
				}
			});
			authorizeDialog.addCloseListner(new EventHandler<ActionEvent>() {
				@Override
				public void handle(ActionEvent event) {
					authorizeDialog.close();
					isDestroy = false;
				}
			});

		}
	}

	public void loginUser() {
		if (!isDestroy) {
			isDestroy = true;
			final AuthorizeUserDialog authorizeDialog = new AuthorizeUserDialog(RouteUtil.mainStage);
			authorizeDialog.addSureListner(new EventHandler<ActionEvent>() {
				public void handle(ActionEvent event) {
					String username = authorizeDialog.getUsername();
					String pwd = authorizeDialog.getPassword();
					if (StrKit.isBlank(username) || StrKit.isBlank(pwd)) {
						authorizeDialog.setMsg("账号和密码不可以空！");
						isDestroy = false;
						return;
					}

					User user = User.dao.findFirst("select * from " + User.TABLE_NAME + " where username=? ", username);
					if (user == null) {
						authorizeDialog.setMsg("账号或密码有误！");
						isDestroy = false;
						return;
					}

					if (!StrKit.equals(PwdUtil.encrypt(pwd), user.getPassword())) {
						authorizeDialog.setMsg("账号或密码有误！");
						isDestroy = false;
						return;
					}

					authorizeDialog.close();
					ProgressStage.of(RouteUtil.mainStage, new Task<Void>() {
						@Override
						protected Void call() throws Exception {
							destroy();
							RouteUtil.goFpr(user);
							return null;
						}
					}, "前往指纹采集页面中...").show();

				}
			});

			authorizeDialog.addCloseListner(new EventHandler<ActionEvent>() {
				@Override
				public void handle(ActionEvent event) {
					authorizeDialog.close();
					isDestroy = false;
				}
			});

		}
	}
}
